import { DataType } from "./utils.js";
import Utils from "./index.js";

class Verify extends Utils {
  static TYPE_LIST = ["string", "array"];

  /**
   * 构造函数，用于创建验证器实例
   * @param {Object} validator 校验规则
   * @param {boolean} integrity 是否不允许校验字段超出校验规则数量，默认为false
   */
  constructor(validator = {}, integrity = false) {
    super();
    this.validator = validator;
    this._validator = validator;
    this.integrity = integrity;
  }

  // 选择校验规则
  selValidator(keys = []) {
    if (keys.length) {
      this.validator = this.objMenuKeys(this._validator, keys);
    } else {
      this.validator = this._validator;
    }
    return this;
  }

  /**
   * 验证数据是否符合规则
   *
   * @param {Object} data 待验证的数据
   * @param {boolean} [required=true] 是否需要所有字段的必填验证都通过
   * @returns {Object} 验证结果，包含是否通过和错误信息
   */
  _verify(data, required = true) {
    if (!this.validator) return { pass: true };
    if (!data || !DataType.checkType(data, "object")) {
      return { pass: false, message: "无效数据" };
    }

    for (let key in data) {
      if (!this.validator[key]) {
        if (this.integrity) {
          return { pass: false, message: `数据中没有${key}字段` };
        } else {
          continue;
        }
      }

      for (let rule of this.validator[key]) {
        let value = data[key];
        let valueType = DataType.getType(value).toLowerCase();

        // 必填验证
        if (rule.required && DataType.isEmpty(value) && required) {
          return { pass: false, message: rule.message || `${key}必填` };
        }

        // 类型验证
        if (rule.type && !DataType.checkType(value, rule.type)) {
          return {
            pass: false,
            message: rule.message || `${key}不是${rule.type}类型`,
          };
        }

        // 长度验证
        if (Verify.TYPE_LIST.includes(valueType)) {
          if (rule.min && value.length < rule.min) {
            return {
              pass: false,
              message: rule.message || `${key}长度小于${rule.min}`,
            };
          }

          if (rule.max && value.length > rule.max) {
            return {
              pass: false,
              message: rule.message || `${key}长度大于${rule.max}`,
            };
          }
        }

        // 数值范围验证
        if (valueType === "number") {
          if (rule.min && value < rule.min) {
            return {
              pass: false,
              message: rule.message || `${key}小于${rule.min}`,
            };
          }

          if (rule.max && value > rule.max) {
            return {
              pass: false,
              message: rule.message || `${key}大于${rule.max}`,
            };
          }
        }

        // 枚举验证
        if (rule.enum && !rule.enum.includes(value)) {
          return {
            pass: false,
            message: rule.message || `${key}不在${rule.enum}枚举值中`,
          };
        }

        // 正则验证
        if (rule.pattern && !rule.pattern.test(value)) {
          return {
            pass: false,
            message: rule.message || `${key}不符合规则`,
          };
        }

        // 自定义验证器验证
        if (rule.validator && !rule.validator(value)) {
          return {
            pass: false,
            message: rule.message || `${key}为通过验证器`,
          };
        }
      }
    }

    return { pass: true };
  }

  /**
   * 验证数据是否符合规则
   *
   * @param {Object} data 待验证的数据
   * @param {boolean} [required=true] 是否需要所有字段的必填验证都通过
   * @returns {boolean} 验证结果，包含是否通过
   * @throws {Error} 验证不通过时抛出错误，包含具体的错误信息
   */
  toVerify(data, required = true) {
    const { pass, message } = this._verify(data, required);
    if (!pass) throw new Error(message);
    return pass;
  }

  /**
   * 验证数据集合是否符合规则
   *
   * @param {array} datalist 待验证的数据集合
   * @param {boolean} [required=true] 是否需要所有字段的必填验证都通过
   * @returns {boolean} 验证结果，包含是否通过
   * @throws {Error} 验证不通过时抛出错误，包含具体的错误信息
   */
  toVerifyArray(arr, required = true) {
    try {
      return arr.every((data) => this.toVerify(data, required));
    } catch (error) {
      throw error;
    }
  }
}

export default Verify;
